package com.woniuxy.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.crypto.SecureUtil;
import com.nimbusds.jose.JOSEException;
import com.woniuxy.dto.RegisterDTO;
import com.woniuxy.dto.UserDTO;
import com.woniuxy.entity.Doctor;
import com.woniuxy.entity.Residents;
import com.woniuxy.entity.User;
import com.woniuxy.mapper.DoctorMapper;
import com.woniuxy.mapper.ResidentsMapper;
import com.woniuxy.mapper.UserMapper;
import com.woniuxy.service.UserService;
import com.woniuxy.util.ConstantUtil;
import com.woniuxy.util.ResponseEnum;
import com.woniuxy.util.ResponseUtil;
import com.woniuxy.utils.JwtUtil;
import org.apache.tomcat.jni.Local;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.util.Date;
import java.util.HashMap;

/**
 * 用户服务实现类
 * 实现用户相关的业务逻辑
 */
@Service("userService")
public class UserServiceImpl implements UserService {
    @Resource
    private UserMapper userMapper;
    @Resource
    private DoctorMapper doctorMapper;
    @Resource
    private ResidentsMapper residentMapper;
    @Resource
    private RedisTemplate redisTemplateInit;

    /**
     * 管理员和医生端的登录
     *
     * @param user 用户信息
     * @return 登录结果
     * @throws JOSEException JWT异常
     */
    @Override
    public ResponseUtil login(User user) throws JOSEException {
        //获取用户登录的密码
        String password = user.getPassword();
        //获取数据库中的匹配的用户信息
        User user1 = userMapper.login(user);
        //密码匹配
        if (user1 == null) {
            return ResponseUtil.get(ResponseEnum.LOGIN_USER_NOT_EXIST);
        } else {
            if (SecureUtil.md5(password).equals(user1.getPassword())
                    && user1.getRoleId() != 4
                    && user1.getStatus() == 1) {
                //将用户的信息放入map中用于jwt的建立
                HashMap<String, Object> map = new HashMap<>();
                HashMap<String, Object> responseMap = new HashMap<>();
                map.put("phoneNum", user1.getPhoneNum());
                map.put("roleId", user1.getRoleId());
                map.put("id", user1.getId());
                //调用工具包中的jwt工具创建jwt
                String token = JwtUtil.getToken(map);
                //将jwt放入map中，返回给前端用于前端拦截器添加到head中
                Doctor doctor = doctorMapper.queryDoctorById(user1.getId());
                responseMap.put("user", doctor);
                responseMap.put("token", token);
                redisTemplateInit.opsForValue().set(ConstantUtil.REDIS_TOKEN_KEY + user1.getId(), token);
                return ResponseUtil.get(ResponseEnum.LOGIN_OK, responseMap);
            } else {
                return ResponseUtil.get(ResponseEnum.LOGIN_USER_PASSWORD_ERROR);
            }
        }
    }

    /**
     * 居民端的登录
     *
     * @param user 用户信息
     * @return 登录结果
     * @throws JOSEException JWT异常
     */
    @Override
    public ResponseUtil residentLogin(User user) throws JOSEException {
        //获取用户登录的密码
        String password = user.getPassword();
        //获取数据库中的匹配的用户信息
        User user1 = userMapper.login(user);
        //密码匹配
        if (user1 == null) {
            return ResponseUtil.get(ResponseEnum.LOGIN_USER_NOT_EXIST);
        } else {
            if (SecureUtil.md5(password).equals(user1.getPassword())
                    && user1.getRoleId() == 4
                    && user1.getStatus() == 1) {
                //将用户的信息放入map中用于jwt的建立
                HashMap<String, Object> map = new HashMap<>();
                HashMap<String, Object> responseMap = new HashMap<>();
                map.put("phoneNum", user1.getPhoneNum());
                map.put("roleId", user1.getRoleId());
                map.put("id", user1.getId());
                //调用工具包中的jwt工具创建jwt
                String token = JwtUtil.getToken(map);
                //将jwt放入map中，返回给前端用于前端拦截器添加到header中
                responseMap.put("token", token);
                Residents resident = residentMapper.queryById(user1.getId());
                responseMap.put("resident", resident);
                redisTemplateInit.opsForValue().set(ConstantUtil.REDIS_TOKEN_KEY + user1.getId(), token);
                return ResponseUtil.get(ResponseEnum.LOGIN_OK, responseMap);
            } else {
                return ResponseUtil.get(ResponseEnum.LOGIN_USER_PASSWORD_ERROR);
            }
        }
    }

    /**
     * 居民端的注册
     *
     * @param registerDTO 用户信息 包含用户的手机号和密码以及角色权限
     *                    return 注册结果
     */
    @Override
    @Transactional
    public ResponseUtil registerResident(RegisterDTO registerDTO) throws InterruptedException {
        // 1. 验证码校验
        String code = (String) redisTemplateInit.opsForValue().get(ConstantUtil.REDIS_CODE_KEY + registerDTO.getPhoneNum());
        if (code == null) {
            return ResponseUtil.get(ResponseEnum.REGISTER_CODE_NOT_EXIST);
        } else if (!registerDTO.getCode().equals(code)) {
            return ResponseUtil.get(ResponseEnum.REGISTER_CODE_ERROR);
        }

        // 2. 验证码正确后，再执行数据库操作
        User user = new User();
        user.setPhoneNum(registerDTO.getPhoneNum());
        user.setPassword(SecureUtil.md5(registerDTO.getPassword()));
        user.setRoleId(registerDTO.getRoleId());
        User user1 = userMapper.login(user);

        if (user1 != null) {
            return ResponseUtil.get(ResponseEnum.REGISTER_USER_EXIST);
        } else {
            // 所有校验通过，执行注册流程
            redisTemplateInit.delete(ConstantUtil.REDIS_CODE_KEY + registerDTO.getPhoneNum());
            Residents resident = new Residents();
            userMapper.register(user);
            // 二次查询获取ID的逻辑
            resident.setPhoneNumber(user.getPhoneNum());
            resident.setLoginId(user.getId());
            resident.setRegisterTime(LocalDate.now());
            residentMapper.addResident(resident);
            return ResponseUtil.get(ResponseEnum.REGISTER_OK);
        }
    }

    /**
     * 密码修改
     * @param userDTO 用户信息
     * @return 修改结果
     */
    @Override
    public ResponseUtil updatePasswordById(UserDTO userDTO) {
        //通过RoleId获取用户信息
        User user = userMapper.queryById(userDTO.getId());
        //密码匹配
        if (!user.getPassword().equals(SecureUtil.md5(userDTO.getOldPassword()))) {
            //密码不匹配回错误
            return ResponseUtil.get(ResponseEnum.UPDATE_USER_PASSWORD_ERROR);
        } else if (user.getPassword().equals(SecureUtil.md5(userDTO.getNewPassword()))) {
            //新密码与旧密码相同
            return ResponseUtil.get(ResponseEnum.UPDATE_USER_PASSWORD_NOT_EQUAL);
        } else {
            user.setPassword(SecureUtil.md5(userDTO.getNewPassword()));
            Integer flag = userMapper.updatePassword(user);
            if (flag > 0) {
                return ResponseUtil.get(ResponseEnum.UPDATE_USER_OK);
            } else {
                return ResponseUtil.get(ResponseEnum.FAIL);
            }
        }
    }

    /**
     * 管理员或医生端的注册
     * @param registerDTO 用户信息 包含用户的手机号和密码以及角色权限
     *                    return 注册结果
     */
    @Override
    @Transactional
    public ResponseUtil registerAdminOrDoctor(RegisterDTO registerDTO) {
        Doctor doctor = new Doctor();
        // 1. 角色ID校验，确保不是居民
        if (registerDTO.getRoleId() == 4) { // 假设角色ID为4是居民
            return ResponseUtil.get(ResponseEnum.FAIL, "此接口仅用于注册管理员或医生");
        }

        // 2. 验证码校验
        String code = (String) redisTemplateInit.opsForValue().get(ConstantUtil.REDIS_CODE_KEY + registerDTO.getPhoneNum());
        if (code == null) {
            return ResponseUtil.get(ResponseEnum.REGISTER_CODE_NOT_EXIST);
        } else if (!registerDTO.getCode().equals(code)) {
            return ResponseUtil.get(ResponseEnum.REGISTER_CODE_ERROR);
        }

        // 3. 检查用户是否存在
        User user = new User();
        doctor.setPhone(registerDTO.getPhoneNum());
        doctor.setRoleId(registerDTO.getRoleId());
        user.setPhoneNum(registerDTO.getPhoneNum());
        User existingUser = userMapper.login(user);

        if (existingUser != null) {
            return ResponseUtil.get(ResponseEnum.REGISTER_USER_EXIST);
        } else {
            // 4. 所有校验通过，执行注册流程
            redisTemplateInit.delete(ConstantUtil.REDIS_CODE_KEY + registerDTO.getPhoneNum());
            user.setPassword(SecureUtil.md5(registerDTO.getPassword()));
            user.setRoleId(registerDTO.getRoleId());
            userMapper.register(user);
            doctor.setLoginId(user.getId());
            doctorMapper.addDoctor(doctor);
            return ResponseUtil.get(ResponseEnum.REGISTER_OK);
        }
    }
}
